package classifieurs;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map.Entry;

import mainprogram.Statistiques;

import extraction.Categorie;
import extraction.Tweet;

public class ClassificationIrrelevantMultinomiale extends Classification {

	public ClassificationIrrelevantMultinomiale(
			HashMap<String, Categorie> statParClasse) {
		super(statParClasse);
	}

	/**
	 * Maps pour ranger les parametres betas - 1 par catégorie: <mot, parametre> 
	 */	
	public HashMap<String, Float> mapRelevant = new HashMap<String, Float>();
	public HashMap<String, Float> mapIrr = new HashMap<String, Float>();

	/**
	 * comptes pour multinomiale
	 */
	public void modeleMultinomial(){
		//<mot <nbDansPositive, nbDansNegative, nbDansNeutral, nbDansIrrelevant>>
		HashMap<String, ArrayList<Float>> mapMulti = new HashMap<String, ArrayList<Float>>();

		ArrayList<Float> tabMapMulti;
		HashMap<String, Integer> hashRelevant = new HashMap<String, Integer>();

		HashMap<String, Integer> hashPos = positive.getMotsOcc();
		HashMap<String, Integer> hashNeg = negative.getMotsOcc();
		HashMap<String, Integer> hashNeu = neutral.getMotsOcc();
		HashMap<String, Integer> hashIrr = irrelevant.getMotsOcc();

		/*Tous les mots dans mapMultinomial avec le tableau correspondant*/
		for(String mot : DataClassification.mots){
			tabMapMulti = new ArrayList<Float>(2);
			if (hashPos.get(mot) == null)
				hashPos.put(mot, 0);
			if (hashNeg.get(mot) == null)
				hashNeg.put(mot, 0);
			if (hashNeu.get(mot) == null)
				hashNeu.put(mot, 0);
			hashRelevant.put(mot, hashPos.get(mot)+hashNeg.get(mot)+hashNeu.get(mot));
			//ajout relevant
			if (hashRelevant.get(mot) == 0)
				tabMapMulti.add(epsilon);
			else
				tabMapMulti.add((float)hashRelevant.get(mot) + epsilon);
			//ajout irrelevant
			if (hashIrr.get(mot) == null)
				tabMapMulti.add(epsilon);
			else
				tabMapMulti.add((float)hashIrr.get(mot) + epsilon);
			mapMulti.put(mot, tabMapMulti);

		}
		/**/

		Float betaRelevant;
		Float betaIrr;
		for (Entry<String, ArrayList<Float>> entry : mapMulti.entrySet()){
			//occurence de ce mot (dans la classe) sur nb tot occurence dans classe
			betaRelevant = entry.getValue().get(0)/ (positive.getOccurencesTotales() + negative.getOccurencesTotales() + neutral.getOccurencesTotales());
			betaIrr = entry.getValue().get(1)/ irrelevant.getOccurencesTotales();
			mapRelevant.put(entry.getKey(), betaRelevant );
			mapIrr.put(entry.getKey(), betaIrr );
		}
	}

	/**
	 * Calcul pourcentage erreur validation croisée pour 1 test
	 * parmis découpe en 10 parties
	 * 1 = test, 9=apprentissage
	 * Répétition 10 fois en changeant bloc test
	 * @return pourcentage erreur pour le test
	 */
	public float validationCroisee(){
		ArrayList<Tweet> listeTweet = test_positive.getListeTweet();
		listeTweet.addAll(test_negative.getListeTweet());
		listeTweet.addAll(test_neutral.getListeTweet());
		listeTweet.addAll(test_irrelevant.getListeTweet());

		int ok=0;
		int nonok=0;
		String sentiment = "";
		for (Tweet t : listeTweet){
			float vraisRelevant = calculVraisemblanceMultinomial(t, mapRelevant);
			float vraisIrr = calculVraisemblanceMultinomial(t, mapIrr);
			float max = (vraisRelevant > vraisIrr) ? vraisRelevant : vraisIrr;
			String max_string = null;
			if (max==vraisRelevant) max_string = "relevant";
			else if (max==vraisIrr) max_string = "irrelevant";

			if (t.getSentiment().equals("test_irrelevant"))
				sentiment = "irrelevant";
			else
				sentiment = "relevant";

			if(sentiment.equals(max_string)){
				ok++;
			}
			else{
				nonok++;
			}
		}
		System.out.println("ok="+ok+" et nonok="+nonok+" --> pourcentage nonok : "+ ((float)nonok/(ok+nonok)));
		return ((float)nonok/(ok+nonok));
	}

	/**
	 * decide si tweet relevant ou irrelevant
	 */
	public void decisionRelevantIrrelevant(){
		ArrayList<Tweet> listeTweet = test_positive.getListeTweet();
		listeTweet.addAll(test_negative.getListeTweet());
		listeTweet.addAll(test_neutral.getListeTweet());
		listeTweet.addAll(test_irrelevant.getListeTweet());

		for (Tweet t : listeTweet){
			float vraisRelevant = calculVraisemblanceMultinomial(t, mapRelevant);
			float vraisIrr = calculVraisemblanceMultinomial(t, mapIrr);
			float max = (vraisRelevant > vraisIrr) ? vraisRelevant : vraisIrr;
			String max_string = null;
			if (max==vraisRelevant) max_string = "relevant";
			else if (max==vraisIrr) max_string = "irrelevant";

			t.setSentiment_test(max_string);
		}

	}

	/**
	 * Calcul vraisemblance pour 1 doc
	 * @param Tweet : document considéré
	 * @param mapCategorie : liste des mots du dico pour cette classe avec leurs parametres respectifs
	 * @return inference : <0, plus elle est proche de 0, plus le Tweet est proche de la catégorie concernée
	 */
	public float calculVraisemblanceMultinomial (Tweet tweet, HashMap<String, Float> mapCategorie){
		float vraisemblance = 0;
		ArrayList<String> tabMotsDoc = 	tweet.getMotsTweetText();
		//parcour map dico
		for (Entry<String, Float> entry : mapCategorie.entrySet()){
			//mot présent dans doc ?
			if (tabMotsDoc.contains(entry.getKey())){
				//vraisemblance 
				vraisemblance += Math.log(entry.getValue());
			}
		}
		return vraisemblance;
	}


	public static void main(String[] args) {
		Statistiques stats = new Statistiques();
		DataClassification d = new DataClassification();
		try {
			stats.analyseFichier("./train.txt"); //remplit statParClasse (analyse avec extraction)
			d.mots_significatifs = stats.getMotsMoinsSignificatifs(); //remplit la map mots_significatifs

			//remplissage des map
			d.analyseFichier("./trainMelange.txt");
			Classification cl;
			float err = 0;
			//TEST irrelevant + polarité
			//zone de test  = bloc 0
			for (int i =0; i<10; i++){
				cl = new ClassificationIrrelevantMultinomiale(d.mapStatParClass.get(i));
				((ClassificationIrrelevantMultinomiale) cl).modeleMultinomial(); 
				//((ClassificationIrrelevantMultinomiale) cl).decisionRelevantIrrelevant();
				err += ((ClassificationIrrelevantMultinomiale) cl).validationCroisee();
				//			cl = new Binomiale_3pol(d.mapStatParClass.get(0));
				//			((Binomiale_3pol) cl).modeleBinomial();
				//			((Binomiale_3pol) cl).decisionPolarité();System.out.println("erreur moyenne : "+ (float)err/10);
				System.out.println("erreur moyenne : "+ (float)err/10);
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}


}
